import uuid
from datetime import datetime

from sqlalchemy import Column, String, DateTime, Integer, Float, Text
from sqlalchemy.orm import declarative_base

from x_pm.db import Session

Base = declarative_base()


def uuid_key() -> str:
    """
    生成 32位 uuid key
    :return:
    """
    return str(uuid.uuid4()).replace('-', '')


class LocTemplateRelation(Base):
    __tablename__ = 'wops_loc_template_relation'

    id = Column(String(32), primary_key=True, nullable=False)
    loc_template_id = Column(String(32), nullable=False, comment='模板id')
    loc_serialkey = Column(String(32), nullable=False, comment='位置编码')
    add_date = Column(DateTime, comment='新建时间')
    edit_date = Column(DateTime, comment='编辑时间')

    def __init__(self, template_id: str, serialkey: str):
        self.id = uuid_key()
        self.loc_template_id = template_id
        self.loc_serialkey = serialkey
        self.add_date = datetime.now()


class FlexChangePlan(Base):
    """
    货位调整计划
    """
    __tablename__ = 'wops_flex_change_plan'

    id = Column(String(32), primary_key=True, nullable=False)
    state = Column(Integer, nullable=False, comment='状态 1 新建、 3:执行中、4已完成')
    # 请求参数输入
    bylane_num = Column(Text, nullable=True, comment='排模巷道')
    change_div_total_num = Column(Integer, nullable=False, comment='需调整货格数')
    befor_change_div_total_num = Column(Integer, nullable=False, comment='调整前货位总数')
    after_change_div_total_num = Column(Integer, nullable=False, comment='调整后货位总数')
    create_data = Column(DateTime, nullable=False, comment='计划生成时间')

    def __init__(self, bylane_num: str, change_div_total_num: int, befor_change_div_total_num: int,
                 after_change_div_total_num: int, create_date: datetime):
        self.id = uuid_key()
        self.state = 1
        self.bylane_num = bylane_num
        self.change_div_total_num = change_div_total_num
        self.befor_change_div_total_num = befor_change_div_total_num
        self.after_change_div_total_num = after_change_div_total_num
        self.create_data = create_date


class FlexChangePlanDtl(Base):
    """
    货位模版调整详情
    """
    __tablename__ = 'wops_flex_change_plan_dtl'

    id = Column(String(32), primary_key=True, nullable=False)
    loc = Column(String(32), nullable=False, comment='loc')
    origin_loc_template = Column(String(32), nullable=False, comment='调整前模板编号')
    traget_loc_template = Column(String(32), nullable=False, comment='调整后模板编号')
    flex_change_planid = Column(String(32), nullable=False, comment='调整计划编号')
    heat_code = Column(String(32), nullable=False, comment='货位热度')

    def __init__(self, loc, origin_loc_template, traget_loc_template, flex_change_planid, heat_code):
        self.id = uuid_key()
        self.loc = loc
        self.origin_loc_template = origin_loc_template
        self.traget_loc_template = traget_loc_template
        self.flex_change_planid = flex_change_planid
        self.heat_code = heat_code


class FlexLocNumChangeRecord(Base):
    """
    货位调整计划生成统计
    """
    __tablename__ = 'wops_flex_loc_num_change_record'

    id = Column(String(32), primary_key=True, nullable=False)
    width = Column(Integer, nullable=False, comment='宽')
    height = Column(Integer, nullable=True, comment='高')
    length = Column(Integer, nullable=False, comment='长')
    befor_need_percent = Column(Float(2, True, 2), nullable=False, comment='调整前百分占比')
    after_change_percent = Column(Float(2, True, 2), nullable=False, comment='调整后百分占比')
    stand_change_percent = Column(Float(2, True, 2), nullable=False, comment='标准统计百分比')
    difference_percent = Column(Float(2, True, 2), nullable=False, comment='与标准差异百分比')
    befor_change_number = Column(Integer, nullable=False, comment='调整前货位数')
    after_cahnge_number = Column(Integer, nullable=False, comment='调整后货位数')
    loc_heat_code = Column(String(32), nullable=False, comment='货位热度编号')
    flex_change_planid = Column(String(32), nullable=False, comment='计划编号')
    heat_code = Column(String(32), nullable=False, comment='货位热度')

    def __init__(self, length, width, height, befor_need_percent, after_change_percent, befor_change_number,
                 after_cahnge_number, flex_change_planid, loc_heat_code, heat_code):
        self.id = uuid_key()
        self.length = length
        self.width = width
        self.height = height
        self.befor_need_percent = befor_need_percent
        self.after_change_percent = after_change_percent
        self.befor_change_number = befor_change_number
        self.after_cahnge_number = after_cahnge_number
        self.flex_change_planid = flex_change_planid
        self.loc_heat_code = loc_heat_code
        self.heat_code = heat_code


class LocTemplateRelationService(object):
    @staticmethod
    def sava_data(data_list: list[LocTemplateRelation]):
        with Session() as sess:
            # TODO: 分批存储???
            sess.add_all(data_list)
            sess.commit()

    @staticmethod
    def clean_data():
        with Session() as sess:
            sess.query(LocTemplateRelation).delete()
            sess.commit()


class FlexService(object):
    """
    货位调整服务
    """

    @staticmethod
    def save_flex_plan(plan: FlexChangePlan):
        """
        存储计划
        :param plan:
        :return:
        """
        with Session() as sess:
            sess.add(plan)
            sess.commit()

    @staticmethod
    def save_flex_plan_dtl(plan_dtl_list: list[FlexChangePlanDtl]):
        """
        存储计划详情
        :param plan_dtl_list:
        :return:
        """
        with Session() as sess:
            sess.add_all(plan_dtl_list)
            sess.commit()

    @staticmethod
    def save_loc_num_change(flncr_list: list[FlexLocNumChangeRecord]):
        """
        货位调整详情存储
        :param flncr_list:
        :return:
        """
        with Session() as sess:
            sess.add_all(flncr_list)
            sess.commit()


class PmOutService(object):
    """
    排摸 输出
    """

    @staticmethod
    def save_result(flex_plan: FlexChangePlan, all_flex_plan_dtl_list: list[list[FlexChangePlanDtl]],
                    flex_flncr_list: list[FlexLocNumChangeRecord], all_relation_list: list[list[LocTemplateRelation]]):
        with Session() as sess:
            # 调整计划
            sess.add(flex_plan)
            # 调整明细
            for flex_plan_dtl in all_flex_plan_dtl_list:
                sess.add_all(flex_plan_dtl)
            # 调整统计
            sess.add_all(flex_flncr_list)
            # 货格 模板 关系 (先清除、再插入)
            sess.query(LocTemplateRelation).delete()
            for relation_list in all_relation_list:
                sess.add_all(relation_list)
            #
            sess.commit()


if __name__ == '__main__':
    pass
